#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>
#include <errno.h>
#include <dirent.h>
#include "structures.h"
#include "mod_config.h"
extern PeerConfig *pconf;

//#include "mod_utils.h"

/*
 * Codice Modulo = 11
 */
int createDirectory(char *basedir, char *nomefile){

    char * strtmp = calloc(strlen(basedir)+strlen(nomefile),1);

    strcat(strtmp,basedir);
    strcat(strtmp,nomefile);
    
    if(mkdir(strtmp,S_IRWXU)<0){
        return 140001;
    }

    return 1;

}
//testata funzionante
int removeDirectory(char *basedir, char *nomefile){
    char * strtmp = calloc(6+strlen(basedir)+strlen(nomefile),sizeof(char));
    char * command = calloc(6,sizeof(char));
    strcpy(command,"rm -r ");

    strcat(strtmp,command);
    strcat(strtmp,basedir);
    strcat(strtmp,nomefile);
    strcat(strtmp,"/");

    if(system(strtmp)==-1){
        printf("errore cancellazione directory\n");
        return 140101;
    }

    return 1;

}

int splitFile(char *basedir, char *nomefile){
    struct stat fileinfo;
    stat(nomefile, &fileinfo);
    long filesize = fileinfo.st_size;

    long readedbyte;
    char *tempbuff;
    tempbuff = (char *)calloc(1241,1);

    char *hashfile = calloc(33,1);
    strcpy(hashfile,hashFile(nomefile));

    char mode = 'r';
    FILE *fd = fopen(nomefile, &mode);
    FILE *fdt = NULL;

    createDirectory(basedir, hashfile);
    strcat(basedir,hashfile);
    char *chunkdir, *tempnewdir, *tempnewfile;

        while(readedbyte<filesize){

            read(fd,tempbuff,10240);
            fseek(fd,10241,SEEK_CUR);
            strcpy(tempnewdir,basedir);
            strcpy(basedir,"~temp");

                fdt = fopen(basedir,"w+");
                write(fdt,tempbuff,10240);
                fclose(fdt);

            strcpy(tempnewfile,hashFile(basedir));
            strcpy(tempnewdir,tempnewfile);

            rename(basedir,tempnewdir);

            readedbyte += 10240;
        }

    fclose(fd);
}

int splitFileAndSend(int *csd, char *basdir, char *nomeFile, int * nC){

    FILE * fi,*fo;

    char *percorso=calloc(strlen(basdir)+strlen(nomeFile),1);

    strcat(strcat(percorso,basdir),nomeFile);

    fi = fopen(percorso,"r");

    char * hashFileTemp = calloc(16,1);

    mdfile(fi,hashFileTemp);

    char * hashF = NULL;

    hashF=(char *)saveDigest(hashFileTemp);
    printf("scrivo qualcosa\n");
    //ho creato la directory con l'hash del file
    createDirectory(pconf->sharedir,hashF);

    //calcolo la dimensione del file
    fseek(fi, 0, SEEK_END);

    size_t size = ftell(fi); //è in byte

    fseek(fi, 0, SEEK_SET);

    printf("Dimensione file in byte: %d \n",size);

    //avendo a disposizione la dimensione in byte posso sapere quanti chunk sono
    //necessari poichè ogni chunk è di 10240 byte.
    int nChunk = (size/10240)+1;

    *(nC)=nChunk;
    printf("Sono necessari %d chunk\n",nChunk);

    int i=0, n=0, m=0;
    char *chunkTemp = calloc(2,1);
    sscanf("aa","%s",chunkTemp);
    for(i=1;i<=nChunk;i++){

        struct chunk * c = (struct chunk *)calloc(1,sizeof(struct chunk));

        strcpy(c->IDF,hashF);

        char *temp = calloc(10240,1);

        n = fread(temp,1,10240,fi);

        strcpy(c->chk,temp);

        char * percorso2 = calloc(strlen(pconf->sharedir)+strlen(hashF)+3,1);
        strcat(strcat(strcat(strcat(percorso2,pconf->sharedir),hashF),"/"),chunkTemp);
        fo = fopen(percorso2,"w+");
        m = fwrite(temp,1,n,fo);
        //calcolo l'hash del file
        fseek(fo, 0, SEEK_SET);
        
        c->size = m;

        char * hashChunkTemp = calloc(17,1);
        mdfile(fo,hashChunkTemp);
        char * hashChunk;

        hashChunk=(char *)saveDigest(hashChunkTemp);

        strcpy(c->ID,hashChunk);

        free(hashChunkTemp);

       // writen(csd,c,sizeof(struct chunk));//da scommentare

        char * percorso3 = calloc(strlen(pconf->sharedir)+strlen(hashF)+32,1);
        strcat(strcat(strcat(strcat(percorso3,pconf->sharedir),hashF),"/"),hashChunk);
        rename( percorso2 , percorso3 );
        free(percorso2);
        free(hashChunk);
        free(percorso3);
        free(temp);
        fclose(fo);
        free(c);
    }

    free(hashFileTemp);

    fclose(fi);
    return 1;
}

int rebuildFile(char * nomeFile, int nChunk, struct chunkLight * cl){
    
    char * percorso = calloc(strlen(pconf->sharedir)-7+5+strlen(nomeFile),1);

    struct chunkLight * clTemp = cl;

    strncpy(percorso,pconf->sharedir,strlen(pconf->sharedir)-7);

    strcat(strcat(percorso,"File/"),nomeFile);
    
    char * percorsoSource = calloc(strlen(pconf->sharedir)+33,1);
    
    strcat(strcat(strcat(percorsoSource,pconf->sharedir),cl->IDF),"/");
    
    FILE *fi,*fo;
    
    fo = fopen(percorso,"a+b");

    int i=0, n=0, m=0;

    for(i=0;i<nChunk;i++){

        char * percorsoSourceTemp = calloc(strlen(pconf->sharedir)+33+33,1);

        strcpy(percorsoSourceTemp,percorsoSource);

        strcat(percorsoSourceTemp,clTemp->ID);

        fi = fopen(percorsoSourceTemp,"r");

        free(percorsoSourceTemp);

        char * temp = calloc(10240,1);

        n = fread(temp, 1, 10240, fi);

        //adesso aggiungiamo al file di destinazione il pezzo

        m = fwrite(temp, 1, n, fo);

        free(temp);

        fclose(fi);

        clTemp++;

    }

    fclose(fo);

    free(percorso);

    free(percorsoSource);

    return 1;
}

int countAllChunk(){
    struct dirent **namelist;
    struct dirent **namelistFile;
    char * incomplete = calloc(14,sizeof(char));
    strcpy(incomplete,"fileIncompleti");
    char * shareIncomplete = calloc(strlen(pconf->sharedir)+strlen(incomplete),sizeof(char));
    int n1=scandir(shareIncomplete, &namelist, 0, alphasort);
    //ho il numero di directory in n1
    int i=0,counter=0,n2=0;
    for(i=2;i<n1;i++){
        char * percorso = calloc(strlen(shareIncomplete)+strlen(namelist[i]->d_name),1);
        strcat(strcat(percorso,shareIncomplete),namelist[i]->d_name);
        strcat(percorso,"/");
        n2=scandir(percorso, &namelistFile, 0, alphasort);
        counter=counter+n2-2;
        n2=0;
        free(percorso);
    }
    return counter;
}
int countAllFile(){
    struct dirent **namelist;
    struct dirent **namelistFile;
    char * complete = calloc(12,sizeof(char));
    strcpy(complete,"fileCompleti");
    char * shareComplete = calloc(strlen(pconf->sharedir)+strlen(complete),sizeof(char));
    int n1=scandir(shareComplete, &namelist, 0, alphasort);
    //ho il numero di directory in n1
    return (n1-2);

}
char * readAllFile(int * nFile){
    struct dirent **namelist;
    struct dirent **namelistFile;
    char * complete = calloc(12,sizeof(char));
    strcpy(complete,"fileCompleti");
    char * shareComplete = calloc(strlen(pconf->sharedir)+strlen(complete),sizeof(char));
    int n1=scandir(shareComplete, &namelist, 0, alphasort);
    //ho il numero di directory in n1
    (*nFile)=n1-2;
    char * hashFile = calloc(nFile,sizeof(char)*33);
    char * ret = hashFile;
    int i=0;
    for(i=2;i<n1;i++){
        strcat(hashFile,namelist[i]->d_name);
        hashFile++;
    }
    return ret;
}
struct chunkLight * readAllChunk(int *nChunkPosseduti){
    //bisogna contare il numero totale di file per poter preparare le strutture
    int nC=countAllChunk();
    (*nChunkPosseduti)=nC;
    struct chunkLight *tmp=calloc(nC,sizeof(struct chunkLight)*nC);//modifica *nC
    struct chunkLight *chk=tmp;
    struct dirent **namelist;
    struct dirent **namelistFile;
    char * incomplete = calloc(14,sizeof(char));
    strcpy(incomplete,"fileIncompleti");
    char * shareIncomplete = calloc(strlen(pconf->sharedir)+strlen(incomplete),sizeof(char));
    int n1=scandir(shareIncomplete, &namelist, 0, alphasort);
    int i=0,j=0;
    int n2=0;
    for(i=2;i<n1;i++){
        printf("%s\n",namelist[i]->d_name);
        //leggo dentro ogni directory presente
        char * percorso = calloc(strlen(shareIncomplete)+strlen(namelist[i]->d_name),1);
        strcat(strcat(percorso,shareIncomplete),namelist[i]->d_name);
        n2=scandir(percorso, &namelistFile, 0, alphasort);
        for(j=2;j<n2;j++){

            printf("    %s\n",namelistFile[j]->d_name);
            printf("La lunghezza della hash del file e': %d\n",strlen(namelist[i]->d_name));
            strcpy(tmp->IDF,namelist[i]->d_name);
            strcpy(tmp->ID,namelistFile[j]->d_name);
            tmp++;
        }
        free(percorso);
    }
    return chk;
};
